import { useEffect, useRef } from "react"

/**
 * 无限滚动自定义Hook
 * @param fetchData 加载数据的回调函数
 * @param hasMore 是否还有更多数据可加载
 * @param loading 当前是否正在加载中
 * @param error 错误对象（可选）
 * @param options 配置选项（可选）
 *   - rootMargin: 触发加载的边界距离（默认"100px"）
 *   - threshold: 触发加载的可见比例阈值（默认0.01）
 *   - debounceTime: 防抖时间（毫秒，默认300）
 * @returns 返回一个ref，需要绑定到滚动区域的底部元素
 */
export default function useInfiniteScroll(
    fetchData: () => void,
    hasMore: boolean,
    loading: boolean,
    error?: unknown,
    options?: {
        rootMargin?: string
        threshold?: number
        debounceTime?: number
    },
) {
    const ref = useRef(null)
    const { rootMargin = "0px", threshold = 0.01, debounceTime = 300 } = options || {}

    useEffect(() => {
        if (hasMore && !loading) {
            let timer: ReturnType<typeof setTimeout> | undefined
            // 创建IntersectionObserver实例
            const observer = new IntersectionObserver(
                (entries) => {
                    const [entry] = entries
                    // 当元素进入视口且没有正在等待的定时器时
                    if (entry.isIntersecting && !timer) {
                        // 设置防抖定时器
                        timer = setTimeout(() => {
                            fetchData()
                        }, debounceTime)
                    }
                },
                {
                    root: null, // 相对于视口观察
                    rootMargin, // 边界距离
                    threshold, // 触发阈值
                },
            )

            // 保存当前的 ref 元素
            const currentElement = ref.current

            // 轮询检查ref.current
            const checkInterval = setInterval(() => {
                if (currentElement) {
                    observer.observe(currentElement)
                    clearInterval(checkInterval) // 停止轮询
                }
            }, 100) // 每100ms检查一次

            // 清理函数
            return () => {
                clearTimeout(timer) // 清除定时器
                clearInterval(checkInterval)
                observer.disconnect() // 停止观察
                if (currentElement) {
                    observer.unobserve(currentElement) // 取消观察特定元素
                }
            }
        }
    }, [hasMore, loading, fetchData, error, rootMargin, threshold, debounceTime])

    return ref
}
